package mybatis.hr.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.jdbc.SQL;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import mybatis.hr.domain.Department;
import mybatis.hr.util.DatabaseManager;

public class DepartmentDAO {
	private static DepartmentDAO instance = new DepartmentDAO();
	
	private SqlSessionFactory factory;
	
	private DepartmentDAO(){
		DatabaseManager manager = DatabaseManager.getInstance();
		factory = manager.getSqlSessionFactory();
	}
	
	public static DepartmentDAO getInstance() {
		return instance;
	}
	/*
	 * SqlSession
	 *  - sql 문 실행 메소드를 제공하는 객체(insert(), update(), delete(), selectOne(), selectList(), selectMap());
	 *  - unchecked 계열의 Exception을 던지므로 try구문안에 작성
	 *  - transaction을 처리
	 *  - 업무흐름당 하나씩 만들어 사용
	 * 코딩패턴
	 *  1. sqlSessionFactory로 부터 sqlSession 객체 조회 - db업무 시작
	 *  2. sql문 실행
	 *  	2-1 DML(insert/update/delete)인 경우 commit처리 필요
	 *  3. 업무 종료 처리(session종료) - close() : finally에서 처리
	 */
	public int insertDepartment(Department department){
		SqlSession session = factory.openSession();
		
		try{
		//매개변수 1. sql문 ID, 2.?에 넣을 값
		int cnt = session.insert("hr.department.insertDepartment", department);
		//commit처리
		session.commit();
		return cnt;
		}finally{
			session.close();
		}
	}
	public int updateDepartment(Department department){
		//1. sql 세션 조회
			SqlSession session = factory.openSession();
		try{
			//쿼리 전송
			int cnt = session.update("hr.department.updateDepartment", department);
			session.commit();
			return cnt;
		}finally{
			//close
			session.close();
		}
	}
	public int deleteDepartmentByNo(int departmentNo){
		SqlSession session = factory.openSession();
		try {
			int cnt = session.delete("hr.department.deleteDepartmentByNo",departmentNo);
			session.commit();
			return cnt;
			
		}finally{
			session.close();
		}
	}
	
	/*
	 * 셀렉의 특별함
	 * sqlSession.selectOne()->얘는 리턴타입이 T 다.T는 resultType에 선언한 타입을 의미한다.<제네릭>
	 * 그런데 얘는 조회 row가 하나일 경우에 사용한다.
	 * sqlSession.selectList()->얘는 리스트를 리턴한다. 얘도 리절트타입에 선언한 타입을 의미한다.
	 * 그런데 얘는 조회 row가 하나 이상일 경우 사용한다. 조회결과를 리스트로 묶어서 리턴한다.
	 * sqlSession.selectMap() -> Map<k,v> 똑같이 리절트 타입에 선언한 타입으로 리턴
	 * 조회 row가 하나 이상인 경우 조회결과를 맵으로 묶어서 리턴
	 * 맵을 사용할때는 예를들어 셀렉에서 받아온 부서객체에서 다시 특정 정보를 키값을 통해 찾아서 사용해야 할때!
	 * 단순히 전체 목록을 다 받아와야 할때는 리스트를 사용한다. 
	 * 근데 리스트를 더 많이 사용한다. 그러니까 selectMap()메서드는 받아온 객체를 맵으로 묶고
	 * selectList()는 가져온 객체를 리스트로 묵어주는 역할을 하는 것이다.
	 */
	public Department selectDepartmentByNo(int departmentNo){
		SqlSession session = factory.openSession();
		try{
			Department dept = session.selectOne("hr.department.selectDepartmentByNo", departmentNo);
			//셀렉의 경우엔 커밋이 필요없다! 데이터를 조작하는게 아니잖아!!!
			return dept;
		}finally{
			session.close();
		}
	}
	public int deleteDepartmentByLocation(String location){
		SqlSession session = factory.openSession();
		try {
			int cnt = session.delete("hr.department.deleteDepartmentByLocation", location);
			session.commit();
			return cnt;
		} finally {
			session.close();
		}
	}
	public List<Department> selectDepartmentList(){
		SqlSession session = factory.openSession();
		try{
			return session.selectList("hr.department.selectDepartmentList");
		}finally{
			session.close();
		}
	}
	//Map은 키값과 벨류값이 모두 객체이기 때문에 int가 아닌 integer를 키값으로 정해야 한다.
	//왜 integer인가? 그 이유는 아래 selectMap의 2번째 매개변수로 departmentNo를 키값으로 사용하겠다고 정의했기 때문이다.
	public Map<Integer, Department> selectDepartmentList_Map(){
		SqlSession session = factory.openSession();
		try{
			//2번 매개변수로는 키로 사용할 프로퍼티를 넣어야 한다.
			return session.selectMap("hr.department.selectDepartmentList", "departmentNo");
			//넘겨줄 파라미터가 있는 경우에는
			//selectMap(String id, Object parameter, String key);
		}finally{
			session.close();
		}
		
	}
	public List<Department> selectDepartmentByLocation(String location){
		SqlSession session = factory.openSession();
		try{
			return session.selectList("hr.department.selectDepartmentByLocation", location);
		}finally{
			session.close();
		}
	}
	public Map<Integer, Department> selectDepartmentByLocation_Map(String location){
		SqlSession session = factory.openSession();
		try{
			return session.selectMap("hr.department.selectDepartmentByLocation", location, "departmentNo");
			
		
		}finally{
			session.close();
		}
	}
	public List<Department> selectDepartmentByName(String name){
		SqlSession session = factory.openSession();
		try {
			return session.selectList("hr.department.selectDepartmentByName", name);
		}finally{
			session.close();
		}
	}
	
}
